RaidComp = LibStub("AceAddon-3.0"):NewAddon("RaidComp", "AceEvent-3.0","AceConsole-3.0","AceTimer-3.0")
local self = RaidComp
_G["RaidComp"] = RaidComp
local addon_name = self:GetName()
local addon_img = "Interface\\Icons\\Spell_Shadow_MindTwisting"

local L = LibStub("AceLocale-3.0"):GetLocale("RaidComp", true)

local LDB = LibStub("LibDataBroker-1.1", true)
local LDBIcon = LDB and LibStub("LibDBIcon-1.0", true)

local TalentQuery = LibStub:GetLibrary("LibTalentQuery-1.0")

local LGT = LibStub:GetLibrary("LibGroupTalents-1.0");

local num = {}
local roster = {}
local colorroster = {}
local chan = "GUILD"
local rankName = {}

local guildIndexByName = {}

local db

local defaults = {
	profile = {
		enable = true,
		duration = 180,
		rank = {},
		inviteAnnouncement = L["RaidComp: New raid start, please type \"/g %s\" to send request"],
		inviteString = "1",
		MinimapIcon = {
			hide = false,
			minimapPos = 220,
			radius = 80,
		},
	}
}

--options
local options = {
	name = addon_name,
	childGroups = "tab", type = "group",
	args = {
		addon = {
			name = L["Addon"],
			order = 1,
			type = "group",
			args = {
				enable = {
					name = L["Enable Addon"],
					type = "toggle",
					desc = L["Enable/Disable"].." "..addon_name,
					order = 11,
					width = "full",
					get = function(info) return self.db.profile[info[#info]] end,
					set = function(info, value)
						self.db.profile[info[#info]] = value
						if (value) then
							self:Enable()
						else
							self:Disable()
						end
					end,
				},
				MinimapIcon = {
					type = "toggle",
					name = L["Show minimap button"],
					desc = L["Show the RaidComp minimap button"],
					order = 12,
					width = "full",
					get = function(info) return not db.MinimapIcon.hide end,
					set = function(info, value)
						db.MinimapIcon.hide = not value
						if value then LDBIcon:Show(addon_name) else LDBIcon:Hide(addon_name) end
					end,
					hidden = function() return not LDBIcon or IsAddOnLoaded("Broker2FuBar") or IsAddOnLoaded("FuBar") end,
				},
			},
		},
		invite = {
			name = L["Raid Invite"],
			order = 2, 
			type = "group",
			disabled = function()
				return not self:IsEnabled()
			end,
			args = {
				duration = {
					name = L["Duration"],
					type = "range",
					desc = L["Set duration"],
					min = 10,
					max = 600,
					step = 10,
					order = 21,
					width = "full",
					get = function(info) return self.db.profile[info[#info]] end,
					set = function(info, value)
						self.db.profile[info[#info]] = value
					end,
				},
				inviteAnnouncement = {
					name = L["Invite Announcement"],
					order = 42,
					type = "input",
					width = "full",
					get = function(info) return self.db.profile[info[#info]] end,
					set = function(info, value)
						self.db.profile[info[#info]] = value
					end,
				},
				inviteString = {
					name = L["Invite key(%s)"],
					order = 43,
					type = "input",
					width = "full",
					get = function(info) return self.db.profile[info[#info]] end,
					set = function(info, value)
						self.db.profile[info[#info]] = value
					end,
				},
				start = {
					name = L["Activate New Raid"],
					order = 44,
					type = "execute",
					width = "full",
					func = function() self:PostSendInvitation() end,
				},
			},
		},
	},
}

function self:OnInitialize()

	self.db = LibStub("AceDB-3.0"):New("RaidCompDB",defaults)
	options.args.profiles = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db)
	options.args.profiles.disabled = function()	return not self:IsEnabled()	end
	
	db = self.db.profile
	LibStub("AceConfig-3.0"):RegisterOptionsTable(addon_name, options)
	LibStub("AceConfigDialog-3.0"):AddToBlizOptions(addon_name, addon_name)
	
	
	options.args.invite.args.rank = {
		type = "multiselect",
		name = L["Guild Rank"],
		order = 25,
		values = function()
			for index = 1 , GuildControlGetNumRanks() do
				rankName[index] = GuildControlGetRankName(index)
			end
			return rankName
		end,
		get = function(_,key) return db.rank[key] end,
		set = function(_,key)
			db.rank[key] = not db.rank[key]
		end,
	}

	if LDB then
		RaidCompLauncher = LDB:NewDataObject(addon_name, {
			type = "launcher",
			icon = addon_img,
			label = addon_name,
			OnClick = function(clickedframe, button)
				if button == "MiddleButton" and self:IsEnabled() then 
					self:PostSendInvitation()
				elseif button == "RightButton" then
					LibStub("AceConfigDialog-3.0"):Open(addon_name)
				elseif button == "LeftButton" and UnitInRaid("player") and self:IsEnabled() then
					for key,_ in pairs(num) do
						if num[key] > 0 then
							SendChatMessage(L[key] .. "(" .. tostring(num[key]) .. "):" .. roster[key],"RAID",nil,nil);
						end
					end
				end
			end,
			OnTooltipShow = function(tip)
				tip:AddLine(addon_name)
				tip:AddLine(L["middle click to activate raid"])
				tip:AddLine(L["left click to announce raid composition"])
				tip:AddLine(L["right click to config"])
				for key,_ in pairs(num) do
					if num[key] > 0 then
						tip:AddLine(L[key] .. "(" .. tostring(num[key]) .. "):" .. colorroster[key]);
					end
				end
			end,
		})
		if LDBIcon and not IsAddOnLoaded("Broker2FuBar") and not IsAddOnLoaded("FuBar") then
			LDBIcon:Register(addon_name, RaidCompLauncher, db.MinimapIcon)
		end
	end
	if not db.MinimapIcon.hide then LDBIcon:Show(addon_name) end
end

function self:OnEnable()
	self:RegisterChatCommand("ri", "PostSendInvitation")
	
	LGT.RegisterCallback(self, "LibGroupTalents_RoleChange")
	LGT.RegisterCallback(self, "LibGroupTalents_Update")
	LGT.RegisterCallback(self, "LibGroupTalents_UpdateComplete")
	LGT.RegisterCallback(self, "LibGroupTalents_Add")
	LGT.RegisterCallback(self, "LibGroupTalents_Remove")
	self:RegisterEvent("RAID_ROSTER_UPDATE")
	self:RegisterEvent("PLAYER_LOGON")
	self:RegisterEvent("PLAYER_ENTERING_WORLD")

end

function self:OnDisble()
	self:UnRegisterChatCommand("ri")
	self:TimerFeedback()

	self:UnregisterEvent("RAID_ROSTER_UPDATE")
	self:UnregisterEvent("PLAYER_LOGON")
	self:UnregisterEvent("PLAYER_ENTERING_WORLD")
end

function self:PLAYER_ENTERING_WORLD()
	for index = 1, GetNumGuildMembers() do
	local name, _, rankIndex, _, _, _, _, _, _, _, _ = GetGuildRosterInfo(index)
	guildIndexByName[name] = rankIndex + 1
	end
end

function self:PostSendInvitation()
	if not self:canInvite() then self:Print(L["You can not invite players now."]) return end
	if UnitAffectingCombat("player") then self:Print(L["You are in combat."]) return end
	SendChatMessage(string.format(db.inviteAnnouncement,db.inviteString), chan);
	self:RegisterEvent("CHAT_MSG_GUILD")
	self:ScheduleTimer("TimerFeedback", db.duration, true)
end

function self:canInvite()
	if GetNumPartyMembers() == 0 then
		return true;
	elseif IsPartyLeader() then
		return true;
	elseif IsRaidLeader() or IsRaidOfficer() then
		return true;
	else
		return false;
	end
end

function self:CHAT_MSG_GUILD(event , message, sender, language, channelString, target, flags, unknown, channelNumber, channelName, unknown, counter)
	
	if not channelName == chan then return end

	if not (message == db.inviteString) then return end

	--if UnitIsUnit(sender, "player") then return end
	----------if UnitInRaid(sender) or UnitInParty(sender) then return end

	local guildRankIndex = guildIndexByName[sender]
	if not self.db.profile.rank[guildRankIndex] then self:Print(sender..": "..L["Wrong Guild Rank"]) return end
	ConvertToRaid()
	InviteUnit(sender)
end

function self:TimerFeedback(arg)
	if arg then self:Print(L["Invitation shutdown."]) end
	self:UnregisterEvent("CHAT_MSG_GUILD")
end

function self:LibGroupTalents_RoleChange(guid, unit, newrole, oldrole)
	self:Calculate()
end

function self:LibGroupTalents_Update()
	self:Calculate()
end

function self:LibGroupTalents_UpdateComplete()
	self:Calculate()
end

function self:LibGroupTalents_Add(guid, unit, name, realm)
	self:Calculate()
end

function self:LibGroupTalents_Remove(guid, name, realm)
	self:Calculate()
end

function self:PLAYER_LOGON()
	self:Calculate()
end

function self:RAID_ROSTER_UPDATE()
	self:Calculate()
end

function self:Calculate()
	num = {
	["tank"] = 0,
	["melee"] = 0,
	["caster"] = 0,
	["healer"] = 0,
	["unknown"] = 0,
	}
	roster = {
	["tank"] = "",
	["melee"] = "",
	["caster"] = "",
	["healer"] = "",
	["unknown"] = "",
	}
	colorroster = {
	["tank"] = "",
	["melee"] = "",
	["caster"] = "",
	["healer"] = "",
	["unknown"] = "",
	}
	
	for index = 1 , GetNumRaidMembers() do
		local name, rank, subgroup, level, class, fileName, zone, online, isDead, role, isML = GetRaidRosterInfo(index)
		self:Analyze(name, rank, subgroup, level, class, fileName, zone, online, isDead, role, isML, index)
	end
	
end

function self:Analyze(name, rank, subgroup, level, class, fileName, zone, online, isDead, role, isML, index)
	if ( subgroup > 5 ) then return end
	
	if not name then return end
	if not online then name = name .. "(" .. L["offline"] .. ")" end
	
	local unitid = "raid"..tostring(index)

	local unitrole = LGT:GetUnitRole(unitid)
	
	if fileName == "HUNTER" then unitrole = "caster" end
	
	unitrole = unitrole or "unknown"
	
	num[unitrole] = num[unitrole] + 1
	roster[unitrole] = roster[unitrole] .. name .. "."
	colorroster[unitrole] = colorroster[unitrole] .. string.format("|cff%.2x%.2x%.2x[%s]|r.", RAID_CLASS_COLORS[fileName].r * 255, RAID_CLASS_COLORS[fileName].g * 255, RAID_CLASS_COLORS[fileName].b * 255, name)

end
